package edu.mit.media.funf.storage;

import java.util.LinkedList;
import java.util.Queue;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public abstract class StorageService extends Service {
  private static final String TAG = StorageService.class.getSimpleName();
  
  public static final String
    ACTION_RECORD = "edu.mit.media.funf.RECORD",
    ACTION_ARCHIVE = "edu.mit.media.funf.ARCHIVE";

  public static final String STORAGE_NAME_KEY = "STORAGE_NAME";
  
  public static final String NAME_KEY = "NAME";
  public static final String VALUE_KEY = "VALUE";
  public static final String TIMESTAMP_KEY = "TIMESTAMP";
  
  private Queue<Intent> intentQueue = null;
  private Thread workingThread = null;

  @Override
  public void onCreate() {
    super.onCreate();
    
    intentQueue = new LinkedList<Intent>();
    
    workingThread = null;
  }
  
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    Log.i(TAG, "onStartCommand()");

    //if this is the first call or something weird has happened to the working thread, init it
    synchronized(TAG) {
      if(workingThread == null || !workingThread.isAlive()){
        Log.w(TAG, "WorkingThread was not running... creating a new one.");
        workingThread = new WorkingThread();
        workingThread.start();
      }
    }
    
    //offer an intent to process to the worker thread
    synchronized(intentQueue){
      if(!intentQueue.offer(intent))
        Log.e(TAG, "Could not add an intent to the IntentQueue.");
    }
    
    //TODO:: fuck!!!
    return START_REDELIVER_INTENT;
  }
  
  @Override
  public void onDestroy() {
    super.onDestroy();
    
    workingThread = null; //the thread should terminate itself

    Log.i(TAG, "Destroyed");
  }
  
  private class WorkingThread extends Thread{
    public WorkingThread(){
      super(new Runnable(){
        @Override
        public void run() {
          Log.i(TAG, "run()");
          
          while(Thread.currentThread().equals(workingThread)){
            try{
              //wait a bit
              Thread.sleep(10);
            }catch(InterruptedException e){
              Log.e(TAG, "Thread.sleep(10) got interrupted!!!???" + e);
            }
            
            //pull the next intent to process
            Intent nextIntent = null;
            synchronized(intentQueue){
              nextIntent = intentQueue.poll();
            }
            //process it
            if(nextIntent != null)
              handleIntent(nextIntent);
          }
        }
        
        public void handleIntent(Intent intent) {
          final String databaseName = intent.getStringExtra(STORAGE_NAME_KEY);
          if (databaseName == null) {
            Log.e(TAG, "Database name not specified.");
            return;
          }
          String action = intent.getAction();
          Log.i(TAG, "onHandleIntent() with Action: " + action);
          if (action == null || action.equals(ACTION_RECORD)) {
            storeIntentData(databaseName, intent);
          } else if (action.equals(ACTION_ARCHIVE)) {
            archiveStoredData(databaseName);
          }
        }});
      }
   }
  
  /**
   * Store the data from the intent into the current storage
   * 
   * @param storageName
   * @param intent
   */
  protected abstract void storeIntentData(String storageName, Intent intent);
  
  /**
   * Archive the current storage into some more permament place.
   * 
   * @param storageName
   */
  protected abstract void archiveStoredData(String storageName);
  
  public IBinder onBind(Intent intent) {
    return null; //not supported by default
  }

}
